package com.lxn.until

import com.lxn.bean.{DauInfo, PageLog}

import java.lang.reflect.{Field, Method, Modifier}
import scala.util.control.Breaks

object MyBeanUtils {

  //首先，我们创建一个可以工具类，帮我们将一个类型的全部数据替换的另一个类型上面
  //因为我们联系用户维度数据，就必须把表数据以及用户活跃数据变成一个专用类，所以创建这个工具就可以帮我们省不少事
  def main(args: Array[String]): Unit = {
    val pageLog: PageLog =
      PageLog("mid1001" , "uid101" , "prov101" , null ,null ,null ,null ,null ,null ,null ,null ,null  ,0L ,123456)

    val dauInfo: DauInfo = new DauInfo()
    println("拷贝前: " + dauInfo)

    copyProperties(pageLog,dauInfo)

    println("拷贝后: " + dauInfo)

  }

  def copyProperties(srcObj : AnyRef , destObj : AnyRef): Unit = {
    //首先判断源类型与目标类型是否为空
    if(srcObj == null || destObj == null){
      //就是其中任何一个为空都不行
      return false
    }
    //不为空接着执行
//    Java 反射机制获取srcObj对象所属类中声明的所有属性，返回一个Field数组
    val srcFields : Array[Field] = srcObj.getClass.getDeclaredFields
    //对所有属性进行循环遍历
    for (srcField <- srcFields){
      Breaks.breakable{
        //get / set
        // Scala 会自动为类中的属性提供 get、 set 方法
        // get : fieldname()
        // set : fieldname_$eq(参数类型)

        val getMethodName : String =  srcField.getName
        val setMethodName : String = srcField.getName+"_$eq"

        //从srcObj里面获取get方法
        val getMethod: Method = srcObj.getClass.getDeclaredMethod(getMethodName)
        //从destObj里面获取set方法  然后就是可能这个里面没有对应的方法，所以需要重新执行，可以抓取错误，不让程序终止
        val setMethod: Method = {
          try {
            destObj.getClass.getDeclaredMethod(setMethodName, srcField.getType)
          } catch {
            //这样捕捉到异常后，不会打断程序，只会换属性执行，直到所有属性被替换掉
            case ex => Breaks.break()
          }
        }
        //然后有些属性，可能是val 或者是final类型的，这种类型一般式不希望改变的，所以我们遇到这种类型应该不做修改
        //首先取出这种类型的属性
        val destField : Field = destObj.getClass.getDeclaredField(srcField.getName)
        //判断是否属于不希望修改的类型
        if(destField.getModifiers.equals(Modifier.FINAL)){
          //不做修改，直接跳过
          Breaks.break()
        }
        setMethod.invoke(destObj,getMethod.invoke(srcObj))
      }

    }
  }

}
